#include "epoll_op.h"
#include "task_cycle.h"

int g_epollfd;

 int socket_bind(const char* ip,int port)
{
    int  listenfd;
    struct sockaddr_in servaddr;
    int reuse=1;
    listenfd = socket(AF_INET,SOCK_STREAM,0);
    if (listenfd == -1)
    {
        perror("socket error:");
        return FAIL;
    }
    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    {
            perror("setsockopet error\n");
            return FAIL;
    }

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET,ip,&servaddr.sin_addr);
    servaddr.sin_port = htons(port);
    if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)
    {
        perror("bind error: ");
        return FAIL;
    }
    return listenfd;
}


 void do_epoll(int listenfd)
{
    int epollfd;
    struct epoll_event events[EPOLLEVENTS];
    int ret;
    
    //创建一个描述符
    epollfd = epoll_create(FDSIZE);
	g_epollfd = epollfd;

    //添加监听描述符事件
    add_event(epollfd,listenfd,EPOLLIN);
    for ( ; ; )
    {
        //获取已经准备好的描述符事件
        ret = epoll_wait(epollfd,events,EPOLLEVENTS,-1);
        handle_events(epollfd,events,ret,listenfd);
    }
    close(epollfd);
}

 void handle_events(int epollfd,struct epoll_event *events,int num,int listenfd)
{
    int i;
    int fd;
	struct epollfd_priv *fd_priv = NULL;
    //进行选好遍历
    for (i = 0;i < num;i++)
    {
    	fd_priv = (struct epollfd_priv *)events[i].data.ptr;
        fd = fd_priv->fd;
	printf("oooooooooooo %d\n", events[i].events);
        //根据描述符的类型和事件类型进行处理
        if ((fd == listenfd) &&(events[i].events & EPOLLIN))
            handle_accpet(epollfd,listenfd);
        else if (events[i].events & EPOLLIN)
        {
            do_read(epollfd,fd_priv);
            fflush(stdout);
        }
        //else if (events[i].events & EPOLLOUT)
            //do_write(epollfd,fd,buf);
    }
}

 void handle_accpet(int epollfd,int listenfd)
{
    int clifd;
    struct sockaddr_in cliaddr;
    socklen_t  cliaddrlen = sizeof(cliaddr);
    clifd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddrlen);
    if (clifd == -1)
        perror("accpet error:");
    else
    {
        printf("accept a new client: %s:%d\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
        //添加一个客户描述符和事件
        add_event(epollfd,clifd,EPOLLIN);
        
    }
}

 void do_read(int epollfd, struct epollfd_priv *fd_priv)
{
    char* data=NULL;
    worker_process(fd_priv,  data);

}

 void do_write(int epollfd,struct epollfd_priv *fd_priv,char *buf)
{
    int nwrite;
	if(fd_priv == NULL)
	{
		perror("fd_priv is NULL \n");
		return;
	}
	int fd = fd_priv->fd;
    nwrite = write(fd,buf,strlen(buf));
    if (nwrite == -1)
    {
        perror("write error:");
        close(fd);
        delete_event(epollfd,fd_priv,EPOLLOUT);
    }
   // else
   //     modify_event(epollfd,fd_priv,EPOLLIN);
}

 void add_event(int epollfd,int fd,int state)
{
    struct epoll_event ev;
    ev.events = state |EPOLLET;//边缘触发
	struct epollfd_priv *fd_priv = NULL;
	fd_priv = (struct epollfd_priv *)malloc(sizeof(struct epollfd_priv));
	if(fd_priv == NULL)
	{
		perror("fd_priv malloc fail !\n");
		return;
	}
	fd_priv->fd = fd;
	fd_priv->status = 0;
    ev.data.ptr = fd_priv;
    epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev);
}

 void delete_event(int epollfd,struct epollfd_priv *fd_priv,int state)
{
	if(fd_priv == NULL)
	{
		perror("fd_priv is NULL \n");
		return;
	}
    struct epoll_event ev;
    ev.events = state|EPOLLET;//边缘触发;
    ev.data.ptr = fd_priv;
	int fd = fd_priv->fd;
    epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev);

	if(fd_priv)
	{
		free(fd_priv);
		fd_priv = NULL;

	}
}

 void modify_event(int epollfd,struct epollfd_priv *fd_priv,int state)
{
	if(fd_priv == NULL)
	{
		perror("fd_priv is NULL \n");
		return;
	}
    printf("-------------- %d\n",fd_priv->fd);
    struct epoll_event ev;
    ev.events = state|EPOLLET;//边缘触发;
    ev.data.ptr = fd_priv;
	int fd = fd_priv->fd;
    epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev);
}

void send_to_user_cb(struct epollfd_priv *fd_priv, char *buf)
{
	do_write(g_epollfd, fd_priv, buf);
}
